package com.richfit.barcodesystem_cczt.network;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.Log;

import com.google.gson.Gson;
import com.richfit.barcodesystem_cczt.activitis.Login;
import com.richfit.barcodesystem_cczt.activitis.model.base.BaseBO;
import com.richfit.barcodesystem_cczt.activitis.model.base.Result;
import com.richfit.barcodesystem_cczt.appcliation.MyAppcliation;
import com.richfit.barcodesystem_cczt.utils.Urls;
import com.richfit.barcodesystem_cczt.utils.sharedPreferences.DatabaseHelper;
import com.richfit.barcodesystem_cczt.utils.toast.ToastUtil;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class OkHttpUtils {
    private static final String TAG = "HttpUtils";
    private static volatile OkHttpUtils instance;
    private static BaseBO bo;
    private final OkHttpClient client;
    public Handler handler = new Handler();
    private Result result = new Result();

    private OkHttpUtils() {
//        File file = new File(Environment.getExternalStorageDirectory(), "cache11");
        client = new OkHttpClient().newBuilder()
                .readTimeout(5, TimeUnit.SECONDS)   //设置读取超时时间
                .connectTimeout(5, TimeUnit.SECONDS) //设置连接的超时时间
//                .addInterceptor(getAppInterceptor())//Application拦截器
//                .cache(new Cache(file, 10 * 1024))
                .build();
    }

    //单例okhttp
    public static OkHttpUtils getInstance() {
        bo = DatabaseHelper.getBaseBO();
        if (instance == null) {
            synchronized (OkHttpUtils.class) {
                if (null == instance) {
                    instance = new OkHttpUtils();
                }
            }
        }
        return instance;
    }

    /**
     * @param bytes
     * @param opts
     * @return Bitmap
     */
    public static Bitmap getPicFromBytes(byte[] bytes,
                                         BitmapFactory.Options opts) {
        if (bytes != null) {
            if (opts != null) {
                return BitmapFactory.decodeByteArray(bytes, 0, bytes.length,
                        opts);
            } else {
                return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            }
        }
        return null;
    }

    private Interceptor getAppInterceptor() {
        //添加拦截器
        Interceptor interceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Log.e("++++++++++", "拦截前");
                //---------请求之前------------
                Response response = chain.proceed(request);
                Log.e("++++++++++", "拦截后");
                //---------请求之后------------
                return response;
            }
        };
        return interceptor;
    }

    private String getUrl(String url) {
        return bo.requestUrl + url;
    }

    public void uploadFile(String url, String token, String imagePath, final NetCallBack netCallBack) {

        try {
            Log.i(TAG, getUrl(url) + ";" + imagePath);
            Log.i(TAG, token);
        } catch (Exception e) {

        }
        File file = new File(imagePath);
        RequestBody image = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", imagePath, image)
                .build();
        Request request = new Request.Builder()
                .url(getUrl(url))
                .addHeader(Urls.AUTH, token)
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showTextShort("获取数据错误！");
                        netCallBack.onFailure(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String r = response.body().string();
                Log.i(TAG, r);
                Gson gson = new Gson();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            result = gson.fromJson(r, Result.class);
                            if (result != null) {
                                if (result.getStatus() == null) {
                                    result.setStatus("500");
                                    result.setInfo("服务器无响应，请稍后再试");
                                }
                                if ("200".equals(result.getStatus())) {
                                    netCallBack.onSuccess(result);
                                } else if ("401".equals(result.getStatus())) {
                                    logout();
                                } else {
                                    ToastUtil.showTextShort(result.getInfo());
                                    netCallBack.onFailure(new Exception(result.getInfo()));
                                }
                            } else {
                                netCallBack.onFailure(new Exception("服务器无响应，请稍后再试"));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            netCallBack.onFailure(new Exception(e.getMessage()));
                        }
                    }
                });
            }
        });

    }

    public void doGetForCode(String url, final NetCallBack netCallBack) {
        try {
            Log.i(TAG, getUrl(url));
        } catch (Exception e) {

        }

        // 2. 创建一个请求对象
        Request request = new Request.Builder()
                .get()
                .url(getUrl(url))
                .build();

        // 3. 创建出一个Call对象
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                Log.i(TAG, "onFailure: " + e.getMessage());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        netCallBack.onFailure(e);
                    }
                });

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 注意：response.body()只能用一次
                Bitmap bitmap = getPicFromBytes(response.body().bytes(), null);
                Log.i(TAG, bitmap.toString());
                //获取头信息
                Headers headers = response.headers();
                //获取cookie
                List<String> cookies = headers.values("Set-Cookie");

                String a[] = cookies.toString().split(";");
                //保存cookie数据
                String cookie = a[0].substring(1);
                result.setStatus(response.code() + "");
                result.setData(bitmap);
                result.setCookie(cookie);
                handler.post(() -> netCallBack.onSuccess(result));
            }
        });
    }

    public void doGet(String url, String cookie, final NetCallBack netCallBack) {
        try {
            Log.i(TAG, "服务地址：" + getUrl(url));
            Log.i(TAG, "Cookie:" + cookie);
        } catch (Exception e) {

        }
        // 2. 创建一个请求对象
        Request request = new Request.Builder()
                .get()
                .url(getUrl(url))//设置请求地址
                .addHeader(Urls.Cookie, cookie)//设置cook（session）
                .build();
        // 3. 创建出一个Call对象
        Post(netCallBack, request);
    }

    public void doPostJson(String url, String cookie, String json, final NetCallBack netCallBack) {
        try {
            Log.i(TAG, "服务地址：" + getUrl(url));
            Log.i(TAG, "Cookie:" + cookie);
            Log.i(TAG, "服传递参数：" + json);
        } catch (Exception e) {

        }
        //指定当前请求的 contentType 为 json 数据
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        Request request = new Request.Builder()
                .url(getUrl(url))
                //设置cook（session）
                .addHeader(Urls.Cookie, cookie)
                .post(RequestBody.Companion.create(json, JSON))
                .build();
        // 3. 创建出一个Call对象
        Post(netCallBack, request);
    }

//    public void doPostMap(String url, String cookie, Map<String, String> params, final NetCallBack netCallBack) {
//        doPostJson(url, cookie, new Gson().toJson(params), netCallBack);
//    }


    public void doPostMap(String url, String cookie, Map<String, String> params, final NetCallBack netCallBack) {

        try {

            Log.i(TAG, "服务地址：" + getUrl(url));
            Log.i(TAG, "Cookie:" + cookie);
            Log.i(TAG, "服传递参数：" + new Gson().toJson(params));
        } catch (Exception e) {

        }
        //不是FormBody，而是一个Builder
        FormBody.Builder body = new FormBody.Builder();
        //key   value
        for (String key : params.keySet()) {
            //value的值
            body.add(key, params.get(key));
        }

        Request request = new Request.Builder()
                .post(body.build())//设置请求参数
                .url(getUrl(url))//设置请求地址
                .addHeader(Urls.Cookie, cookie)//设置cook（session）
                .addHeader("Content-Type", Urls.JSON_TYPE)//设置请求类别（json）
                .build();
        // 3. 创建出一个Call对象
        Post(netCallBack, request);
    }

    private void Post(NetCallBack netCallBack, Request request) {
        Call call = client.newCall(request);
        call.enqueue(new Callback() {

            @Override
            public void onFailure(Call call, final IOException e) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showTextShort("获取数据错误！");
                        Log.i(TAG + "错误信息：", "run: " + e);
                        netCallBack.onFailure(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                String r = response.body().string();
                Log.i(TAG + "返回结果", r);
                Gson gson = new Gson();
                handler.post(() -> {
                    try {
                        if (r.startsWith("<!DOCTYPE html>")) {
                            result.setInfo("登陆超时，跳转到登陆页面");
                            netCallBack.onFailure(new Exception(result.getInfo()));
                            logout();
                            return;
                        }
                        result = gson.fromJson(r, Result.class);
                        if (result != null) {
                            if (result.getStatus() == null) {
                                result.setStatus(Result.err);
                                result.setInfo("服务器无响应，请稍后再试");
                            }
                            if (result.getStatus().equals(Result.succ)) {
                                netCallBack.onSuccess(result);
                            } else if ("401".equals(result.getStatus())) {
                                result.setInfo("登陆超时，跳转到登陆页面");
                                netCallBack.onFailure(new Exception(result.getInfo()));
                                logout();
//                            } else if (result.getStatus().equals(Result.err)) {
//                                ToastUtil.showTextShort(result.getInfo());
//                                netCallBack.onFailure(new Exception(result.getInfo()));
                            } else {
                                //判断是否未登录，session过期
                                // {status: "error", info: "用户未登录，拒绝访问", data: null
                                ToastUtil.showTextShort(result.getInfo());
                                netCallBack.onFailure(new Exception(result.getInfo()));
                                if (result.getInfo().startsWith("用户未登录")) {
                                    logout();
                                }
                            }
                        } else {
                            netCallBack.onFailure(new Exception("服务器无响应，请稍后再试"));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        netCallBack.onFailure(new Exception(e.getMessage()));
                    }
                });
            }

        });
    }

    private void logout() {

        Intent intent = new Intent(MyAppcliation.context.getApplicationContext(), Login.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("type", 1);
        MyAppcliation.context.startActivity(intent);
    }

    public interface NetCallBack {
        void onSuccess(Result r);

        void onFailure(Exception e);
    }

}
